// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.

namespace Microsoft.Samples.Commerce.Order.CommerceEntities
{
    using Microsoft.Commerce.Contracts;

    /// <summary>
    /// Represents an address.
    /// </summary>
    public class Address : ICommerceEntity
    {
        /// <summary>
        /// defines the model name for this commerce entity
        /// </summary>
        public const string ModelNameDefinition = "Address";

        /// <summary>
        /// The commerce entity.
        /// </summary>
        private CommerceEntity commerceEntity;

        /// <summary>
        /// Initializes a new instance of the <see cref="Address"/> class
        /// </summary>
        public Address()
        {
            this.commerceEntity = new CommerceEntity(Address.ModelNameDefinition);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Address"/> class
        /// </summary>
        /// <param name="commerceEntity">The commerce entity.</param>
        public Address(CommerceEntity commerceEntity)
        {
            this.commerceEntity = commerceEntity;
        }

        #region ICommerceEntity Members

        /// <summary>
        /// Gets or sets the id.
        /// </summary>
        /// <value>The id of the entity.</value>
        public string Id
        {
            get { return this.commerceEntity.Id; }
            set { this.commerceEntity.Id = value; }
        }

        /// <summary>
        /// Gets or sets the type name of this object instance
        /// <remarks>Required so that the Builders can convert to the Multi-channel Commerce Foundation CommerceEntity base type</remarks>
        /// </summary>
        /// <value></value>
        public string ModelName
        {
            get { return this.commerceEntity.ModelName; }
            set { this.commerceEntity.ModelName = value; }
        }

        /// <summary>
        /// Gets or sets this objects collection of Properties and their corresponding values
        /// </summary>
        /// <value></value>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "Collection setting is required")]
        public CommercePropertyCollection Properties
        {
            get { return this.commerceEntity.Properties; }
            set { this.commerceEntity.Properties = value; }
        }

        #endregion

        /// <summary>
        /// Gets or sets a descriptive name of the address. Unique per user.
        /// </summary>
        /// <value>The name of the address.</value>
        public string AddressName
        {
            get { return this.commerceEntity.GetPropertyValue(PropertyName.AddressName) as string; }
            set { this.commerceEntity.SetPropertyValue(PropertyName.AddressName, value); }
        }

        /// <summary>
        /// Gets or sets the city associated with the address.
        /// </summary>
        /// <value>The name of the city associated to the Address.</value>
        public string City
        {
            get { return this.commerceEntity.GetPropertyValue(PropertyName.City) as string; }
            set { this.commerceEntity.SetPropertyValue(PropertyName.City, value); }
        }

        /// <summary>
        /// Gets or sets the country/region code associated with the address.
        /// </summary>
        /// <value>The region code.</value>
        public string CountryRegionCode
        {
            get { return this.commerceEntity.GetPropertyValue(PropertyName.CountryRegionCode) as string; }
            set { this.commerceEntity.SetPropertyValue(PropertyName.CountryRegionCode, value); }
        }

        /// <summary>
        /// Gets or sets the country/region name associated with the address.
        /// </summary>
        /// <value>The region name.</value>
        public string CountryRegionName
        {
            get { return this.commerceEntity.GetPropertyValue(PropertyName.CountryRegionName) as string; }
            set { this.commerceEntity.SetPropertyValue(PropertyName.CountryRegionName, value); }
        }

        /// <summary>
        /// Gets or sets the first line of the address.
        /// </summary>
        /// <value>The line1.</value>
        /// <remarks>The first line of an address. For example,  1 Main Street.</remarks>
        public string Line1
        {
            get { return this.commerceEntity.GetPropertyValue(PropertyName.Line1) as string; }
            set { this.commerceEntity.SetPropertyValue(PropertyName.Line1, value); }
        }

        /// <summary>
        /// Gets or sets the second line of the address.
        /// </summary>
        /// <value>The line1.</value>
        /// <remarks>The second line of an address.</remarks>
        public string Line2
        {
            get { return this.commerceEntity.GetPropertyValue(PropertyName.Line2) as string; }
            set { this.commerceEntity.SetPropertyValue(PropertyName.Line2, value); }
        }

        /// <summary>
        /// Gets or sets the first name of the address.
        /// </summary>
        /// <value>The firts name.</value>
        /// <remarks>The first name of an address..</remarks>
        public string FirstName
        {
            get { return this.commerceEntity.GetPropertyValue(PropertyName.FirstName) as string; }
            set { this.commerceEntity.SetPropertyValue(PropertyName.FirstName, value); }
        }

        /// <summary>
        /// Gets or sets the last name of the address.
        /// </summary>
        /// <value>The last name.</value>
        /// <remarks>The last name of an address.</remarks>
        public string LastName
        {
            get { return this.commerceEntity.GetPropertyValue(PropertyName.LastName) as string; }
            set { this.commerceEntity.SetPropertyValue(PropertyName.LastName, value); }
        }

        /// <summary>
        /// Gets or sets the phone number of the address.
        /// </summary>
        /// <value>The phone number.</value>
        /// <remarks>The phone of an address.</remarks>
        public string PhoneNumber
        {
            get { return this.commerceEntity.GetPropertyValue(PropertyName.PhoneNumber) as string; }
            set { this.commerceEntity.SetPropertyValue(PropertyName.PhoneNumber, value); }
        }

        /// <summary>
        /// Gets or sets the State/Province code associated with the address.
        /// </summary>
        /// <value>The name of the State/Province code associated to the Address.</value>
        public string StateProvinceCode
        {
            get { return this.commerceEntity.GetPropertyValue(PropertyName.StateProvinceCode) as string; }
            set { this.commerceEntity.SetPropertyValue(PropertyName.StateProvinceCode, value); }
        }

        /// <summary>
        /// Gets or sets the State/Province name associated with the address.
        /// </summary>
        /// <value>The name of the State/Province name associated to the Address.</value>
        public string StateProvinceName
        {
            get { return this.commerceEntity.GetPropertyValue(PropertyName.StateProvinceName) as string; }
            set { this.commerceEntity.SetPropertyValue(PropertyName.StateProvinceName, value); }
        }

        /// <summary>
        /// Gets or sets the postal code or ZIP code associated with the address.
        /// </summary>
        /// <value>The postal code.</value>
        public string ZipPostalCode
        {
            get { return this.commerceEntity.GetPropertyValue(PropertyName.ZipPostalCode) as string; }
            set { this.commerceEntity.SetPropertyValue(PropertyName.ZipPostalCode, value); }
        }

        /// <summary>
        /// Gets or sets the address type.
        /// </summary>
        public int? AddressType
        {
            get { return this.commerceEntity.GetPropertyValue(PropertyName.AddressType) as int?; }
            set { this.commerceEntity.SetPropertyValue(PropertyName.AddressType, value); }
        }

        #region Implicit operators
        /// <summary>
        /// Toes the user profile.
        /// </summary>
        /// <param name="commerceEntity">The commerce entity.</param>
        /// <returns></returns>
        public static implicit operator Address(CommerceEntity commerceEntity)
        {
            return new Address(commerceEntity);
        }
        #endregion

        /// <summary>
        /// Required so that the Builders can convert to the Multi-channel Commerce Foundation CommerceEntity base type using <see cref="ModelName"/>
        /// </summary>
        /// <returns>This instances base type</returns>
        public CommerceEntity ToCommerceEntity()
        {
            return this.commerceEntity;
        }

        /// <summary>
        /// Names of the properties exposed by this commerce entity.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Justification = "Needed for external access"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1053:StaticHolderTypesShouldNotHaveConstructors", Justification = "Cannot make it private as it cannot be derived from")]
        public class PropertyName : CommerceEntity.PropertyName
        {
            /// <summary>
            /// The name of the AddressName property for an Address.
            /// </summary>
            public const string AddressName = "AddressName";

            /// <summary>
            /// The name of the City property for an Address.
            /// </summary>
            public const string City = "City";

            /// <summary>
            /// The name of the CountryRegionCode property for an Address.
            /// </summary>
            public const string CountryRegionCode = "CountryRegionCode";

            /// <summary>
            /// The name of the CountryRegionName property for an Address.
            /// </summary>
            public const string CountryRegionName = "CountryRegionName";

            /// <summary>
            /// The name of the Line1 property for an Address.
            /// </summary>
            public const string Line1 = "Line1";

            /// <summary>
            /// The name of the Line2 property for an Address.
            /// </summary>
            public const string Line2 = "Line2";

            /// <summary>
            /// The name of the FirstName property for an Address.
            /// </summary>
            public const string FirstName = "FirstName";

            /// <summary>
            /// The name of the LastName property for an Address.
            /// </summary>
            public const string LastName = "LastName";

            /// <summary>
            /// The name of the PhoneNumber property for an Address.
            /// </summary>
            public const string PhoneNumber = "Telephone";

            /// <summary>
            /// The name of the StateProvinceCode property for an Address.
            /// </summary>
            public const string StateProvinceCode = "StateProvinceCode";

            /// <summary>
            /// The name of the StateProvinceName property for an Address.
            /// </summary>
            public const string StateProvinceName = "StateProvinceName";

            /// <summary>
            /// The name of the ZipPostalCode property for an Address.
            /// </summary>
            public const string ZipPostalCode = "ZipPostalCode";

            /// <summary>
            /// The name of the AddressType property for an Address.
            /// </summary>
            public const string AddressType = "AddressType";
        }
    }
}
